<template>
  <div class="upload">
    <!--      :http-request="httpRequest"-->

    <el-upload
      v-model:file-list="fileList"
      ref="uploadRefs"
      :action="action"
      :multiple="multiple"
      :limit="limit"
      :show-file-list="false"
      :headers="headers"
      :data="data"
      :on-progress="handleProgress"
      :on-success="handleSuccess"
      :on-exceed="handleExceed"
      :on-error="handleError"
      :accept="getAccept"
    >
      <slot />
    </el-upload>
    <el-dialog
      v-if="showProgress && fileList.length"
      v-model="visible"
      z-index="99"
      title="上传进度"
      :close-on-click-modal="false"
      width="500px"
      :modal="false"
      @close="handleClose"
      @open="handleOpen"
    >
      <div
        class="file-list p-4"
        v-loading.body.fullscreen.lock="loadingInstance"
        element-loading-text="上传中..."
        element-loading-custom-class="loading-class"
      >
        <template v-for="(item, index) in fileList" :key="index">
          <div class="mb-5">
            <div>{{ item.name }}</div>
            <div class="flex-1">
              <el-progress :percentage="parseInt(item.percentage)" />
            </div>
          </div>
        </template>
      </div>
    </el-dialog>
  </div>
</template>

<script lang="ts">
import { type ElUpload } from 'element-plus'
import { computed, defineComponent, ref, shallowRef } from 'vue'

import config from '@/config'
import { RequestCodeEnum } from '@/enums/requestEnums'
import useUserStore from '@/stores/modules/user'
import feedback from '@/utils/feedback'
import uploadFile from '@/utils/uploadFile'

export default defineComponent({
  components: {},
  props: {
    // 上传文件类型
    type: {
      type: String,
      default: 'image'
    },
    // 是否支持多选
    multiple: {
      type: Boolean,
      default: true
    },
    // 多选时最多选择几条
    limit: {
      type: Number,
      default: 10
    },
    // 上传时的额外参数
    data: {
      type: Object,
      default: () => ({})
    },
    // 是否显示上传进度
    showProgress: {
      type: Boolean,
      default: false
    }
  },
  emits: ['change', 'error', 'success', 'allSuccess'],
  mounted() {
    document.body.removeEventListener('paste', this.handlePaste)
    document.body.addEventListener('paste', this.handlePaste)
  },
  unmounted() {
    document.body.removeEventListener('paste', this.handlePaste)
  },
  setup(props, { emit }) {
    const loadingInstance = ref()
    const userStore = useUserStore()
    const uploadRefs = shallowRef<InstanceType<typeof ElUpload>>()
    const action = ref(`${config.baseUrl}${config.urlPrefix}/upload/${props.type}`)
    const headers = computed(() => ({
      token: userStore.token,
      version: config.version
    }))
    const visible = ref(false)
    const fileList = ref<any[]>([])

    const handleProgress = () => {
      visible.value = true
    }
    let uploadLen = 0
    const handleSuccess = (response: any, file: any) => {
      uploadLen++
      if (uploadLen == fileList.value.length) {
        uploadLen = 0
        fileList.value = []
        emit('allSuccess')
      }
      emit('change', file)
      if (response.code == RequestCodeEnum.SUCCESS) {
        emit('success', response)
      }
      if (response.code == RequestCodeEnum.FAIL && response.msg) {
        feedback.msgError(response.msg)
      }
    }
    const handleError = (event: any, file: any) => {
      uploadLen++
      if (uploadLen == fileList.value.length) {
        uploadLen = 0
        fileList.value = []
        emit('allSuccess')
      }
      feedback.msgError(`${file.name}文件上传失败`)
      uploadRefs.value?.abort(file)
      visible.value = false
      emit('change', file)
      emit('error', file)
    }
    const handleExceed = () => {
      feedback.msgError(`超出上传上限${props.limit}，请重新上传`)
    }
    const handleClose = async () => {
      fileList.value = []
      await nextTick()
      loadingInstance.value = false
      visible.value = false
    }

    const httpRequest = async (options: any) => {
      return await uploadFile.uploadFile(options.file, (p) => {
        fileList.value.find((v: any) => v.uid === options.file.uid).percentage = p * 100
        handleProgress()
      })
    }

    const handleOpen = () => {
      loadingInstance.value = true
    }

    const getAccept = computed(() => {
      switch (props.type) {
        case 'image':
          return '.jpg,.png,.gif,.jpeg,.ico'
        case 'video':
          return '.wmv,.avi,.mpg,.mpeg,.3gp,.mov,.mp4,.flv,.rmvb,.mkv'
        default:
          return '*'
      }
    })

    const handlePaste = (event: any) => {
      const data = event.clipboardData || window.clipboardData
      const items = data.items
      if (items && items.length) {
        // 检索剪切板items
        // 限制上传文件类型
        for (let i = 0; i < items.length; i++) {
          const file = items[i]?.getAsFile()
          if (file) {
            uploadRefs.value?.handleStart(file)
          }
        }
        uploadRefs.value?.submit()
      }
    }

    //剪切板上传图片
    return {
      uploadRefs,
      action,
      headers,
      visible,
      fileList,
      getAccept,
      loadingInstance,
      handleProgress,
      handleSuccess,
      handleError,
      handleExceed,
      handleClose,
      httpRequest,
      handleOpen,
      handlePaste
    }
  }
})
</script>

<style lang="scss">
.loading-class {
  z-index: 9999;
}
</style>
